/*
 * SubstrateModel.h
 *
 *      Author: Jerome RD Soine and Christoph A Brand
 *      Institution: Schwarz goup, Institute for Theoretical Physics, Heidelberg University, Germany
 */

#ifndef SUBSTRATEMODEL_H_
#define SUBSTRATEMODEL_H_

#include <vector>
#include <string>
#include "ForceTransmission.h"
#include <iostream>

using namespace std;

/*!
 *  \brief Abstract class for implementation of SubstrateModels. Can be extended to implement custom substrate models.
 *
 *  Abstract class from which specific substrate models can be derived. It provides a set of virtual functions,
 *  which must be implement in order to use it in combination with CellModel and Optimization. The substrate model
 *  gets a vector of ForceTransmission objects in its run function, from which it needs to calculate the corresponding
 *  substrate displacements. After the call of the run function it needs to provide substrate displacement
 *  information via the get_displacement_at function. The function write_output is called after run and can be used to
 *  write the current state of the substrate, but can be left blank as well. It is important to provide a clone()
 *  function, as this is heavily used by the optimization procedure. The returned SubstrateModel object should behave
 *  like the template, but should have no common memory resources.
 */

class SubstrateModel {
public:
	/*!
	 * Class Deconstructor.
	 */
	virtual ~SubstrateModel() {};
	/*!
	 * Clones a SubstrateModel object. This function is heavily used by Worker.h in order to provide multi-threading. The returned SubstrateModel object should behave like the template, but should have no common memory resources.
	 */
	virtual SubstrateModel * clone() const = 0;
	/*!
	 * Calculates the substrate deformation from a vector of ForceTransmission objects. This function incorporates the key logic of the substrate model. Should save ForceTransmission vector to protected variable.
	 */
	virtual void run(vector<ForceTransmission*> force_transmissions) = 0;
	/*!
	 * Returns the displacements at a given position. Is only called after the run function.
	 */
	virtual vector<double> get_displacement_at (vector<double> point) = 0;
	/*!
	 * Return list of displacements associated with a list of positions.
	 */
	virtual vector<vector<double> > get_displacement_list_at(vector<vector<double> > points)
	{
		vector<vector<double> > list;
		for(unsigned int i=0;i<points.size();i++){
			list.push_back(get_displacement_at(points[i]));
		}
		return list;
	}
	/*!
	 * Opportunity to write output files. This function is called after the run function. Can be implemented with no functionality.
	 */
	virtual void write_output(string filename) = 0;
	/*!
	 * Get ForcesTransmission objects previously supplied to the run function.
	 */
	vector<ForceTransmission*> get_force_transmissions(){return force_trans;};

protected:
	/*!
	 * Saves current ForceTransmission object
	 */
	vector<ForceTransmission*> force_trans;

};


#endif /* SUBSTRATEMODEL_H_ */
